#include "cWebConnection.h"


#define _IS_VALID_LANG(a) a < 3 && a >= 0 ? 0 : 1
#define _LANG_DE "lang=de"
#define _LANG_FR "lang=fr"
#define _LANG_EN "lang=en"
#define _MAP_ID "&map_id="
#define _EVENT_ID "&event_id="



wchar_t* convertToWideChar(char* toConvert){
	int len;
	int slength = strlen(toConvert) + 1;
	wchar_t *buf;
	len = MultiByteToWideChar(CP_ACP, 0, toConvert, slength, 0, 0); 
    buf = (wchar_t*)malloc(sizeof(wchar_t)*len);
    MultiByteToWideChar(CP_ACP, 0, toConvert, slength, buf, len);
	return buf;
}


char* __crecieve_server_response(HINTERNET handle){
	char *buffer, recv;
	int pos, buff_len, utf8char;
	DWORD bytes;
	LPVOID lpBuffer;

	lpBuffer = 0;
	bytes = 0;
retry:
	if(!HttpQueryInfo(handle, HTTP_QUERY_STATUS_CODE, lpBuffer, &bytes, NULL)){
		lpBuffer = malloc(bytes);
		goto retry;
	}
	if(atoi((char*)lpBuffer) != 200){
		free(lpBuffer);
		return 0;
	}
	free(lpBuffer);

	utf8char = pos = 0;
	buff_len = 1;
	buffer = (char*)malloc(buff_len);
	while(InternetReadFile(handle, &recv, 1, &bytes) != 0){
		if(bytes != 1)
			break;
		if(pos+2 >= buff_len){
			buff_len *= 2;
			buffer = (char*)realloc(buffer, buff_len);
		}
		if(recv == -61 && utf8char==0){
			utf8char = 1;
			continue;
		}
		if(utf8char == 1){
			utf8char = 0;
			switch(recv){
			case -92:
				buffer[pos] =  'a';
				buffer[pos+1] = 'e';
				break;
			case -74:
				buffer[pos] =  'o';
				buffer[pos+1] = 'e';
				break;
			case -68:
				buffer[pos] =  'u';
				buffer[pos+1] = 'e';
				break;
			case -97:
				buffer[pos] = 's';
				buffer[pos+1] = 's';
				break;
			case -124:
				buffer[pos] =  'A';
				buffer[pos+1] = 'e';
				break;
			case -106:
				buffer[pos] =  'O';
				buffer[pos+1] = 'e';
				break;
			case -100:
				buffer[pos] =  'U';
				buffer[pos+1] = 'e';
				break;
			}
			pos += 2;
			continue;
		}
		buffer[pos] = recv;
		pos++;
	}
	buffer[pos] = '\0';
	return buffer;
}


char* __cserver_request(const char *param){
	char *buffer;
	wchar_t *b;
	HINTERNET openHandle, sessionHandle, queryHandle;
	
	if((openHandle = InternetOpen(TEXT(APP_ID), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0)) == 0){
		return 0;
	}
	if((sessionHandle = InternetConnect(openHandle, TEXT(API_SERVER), INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0)) == 0){
		InternetCloseHandle(openHandle);
		return 0;
	}
	//b = convertToWideChar((char*)param);
	if((queryHandle = HttpOpenRequestA(sessionHandle, NULL, param, NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0)) == 0){
		InternetCloseHandle(sessionHandle);
		InternetCloseHandle(openHandle);
		//free(b);
		return 0;
	}
	//free(b);
	if(HttpSendRequest(queryHandle, NULL, 0, NULL, 0) == 0){
		InternetCloseHandle(queryHandle);
		InternetCloseHandle(sessionHandle);
		InternetCloseHandle(openHandle);
		return 0;
	}
	buffer = __crecieve_server_response(queryHandle);
	InternetCloseHandle(queryHandle);
	InternetCloseHandle(sessionHandle);
	InternetCloseHandle(openHandle);
	return buffer;
}

//sends a worldmapping request to the server, returns the recieved answer as a string
char* _worldMappingRequest(int lang){
	char *request, *recv;
	int req_len;
	if(_IS_VALID_LANG(lang) != 0)
		return 0;
	req_len = strlen(WORLD_MAPPING_API)+strlen(_LANG_DE)+1;
	request = (char*)malloc(req_len);
	memset(request, '\0', req_len);
	strcpy_s(request, req_len, WORLD_MAPPING_API);
	switch(lang){
	case GW2API_LANG_DE:
		strcat_s(request, req_len, _LANG_DE);
		break;
	case GW2API_LANG_FR:
		strcat_s(request, req_len, _LANG_FR);
		break;
	case GW2API_LANG_EN:
		strcat_s(request, req_len, _LANG_EN);
		break;
	}
	recv = __cserver_request(request);
	free(request);
	return recv;
}

//sends a mapmapping request to the server, returns the recieved answer as a string
char* _mapMappingRequest(int lang){
	char *request, *recv;
	int req_len;
	if(_IS_VALID_LANG(lang) != 0)
		return 0;
	req_len = strlen(MAP_MAPPING_API)+strlen(_LANG_DE)+1;
	request = (char*)malloc(req_len);
	memset(request, '\0', req_len);
	strcpy_s(request, req_len, MAP_MAPPING_API);
	switch(lang){
	case GW2API_LANG_DE:
		strcat_s(request, req_len, _LANG_DE);
		break;
	case GW2API_LANG_FR:
		strcat_s(request, req_len, _LANG_FR);
		break;
	case GW2API_LANG_EN:
		strcat_s(request, req_len, _LANG_EN);
		break;
	}
	recv = __cserver_request(request);
	free(request);
	return recv;
}

//sends an eventmapping request to the server, returns the recieved answer as a string
char* _eventMappingRequest(int lang){
	char *request, *recv;
	int req_len;
	if(_IS_VALID_LANG(lang) != 0)
		return 0;
	req_len = strlen(EVENT_MAPPING_API)+strlen(_LANG_DE)+1;
	request = (char*)malloc(req_len);
	memset(request, '\0', req_len);
	strcpy_s(request, req_len, EVENT_MAPPING_API);
	switch(lang){
	case GW2API_LANG_DE:
		strcat_s(request, req_len, _LANG_DE);
		break;
	case GW2API_LANG_FR:
		strcat_s(request, req_len, _LANG_FR);
		break;
	case GW2API_LANG_EN:
		strcat_s(request, req_len, _LANG_EN);
		break;
	}
	recv = __cserver_request(request);
	free(request);
	return recv;
}

//sends an eventstate request to the server, returns the recieved answer as a string @param: strPtr world_id, map_id, event_id
char* _eventStateRequest(const char *world_id, const char *map_id, const char *event_id){
	char *request, *recv;
	int req_len;
	
	if(world_id == 0)
		return 0;
	req_len = strlen(DYNAMIC_EVENTS_API) + strlen(world_id) + (map_id == 0 ? 0 : strlen(map_id)+ strlen(_MAP_ID)) 
		+ (event_id == 0 ? 0 : strlen(event_id)+ strlen(_EVENT_ID))+1;
	request = (char*)malloc(req_len);
	memset(request, '\0', req_len);
	strcpy_s(request, req_len, DYNAMIC_EVENTS_API);
	strcat_s(request, req_len, world_id);
	if(map_id != 0)
		strcat_s(request, req_len, map_id);
	if(event_id != 0)
		strcat_s(request, req_len, event_id);
	recv = __cserver_request(request);
	free(request);
	return recv;
}

//requests the current matchmapping from the server
char* _matchMappingRequest(){
	char *request, *recv;
	int req_len;

	req_len = strlen(WVW_MATCHES) + 1;
	request = (char*)malloc(req_len);
	memset(request, '\0', req_len);
	strcpy_s(request, req_len, WVW_MATCHES);
	recv = __cserver_request(request);
	free(request);
	return recv;
}

//requests a match's details from the server @param: strPtr match_id
char* _matchDetailsRequest(const char *match_id){
	char *request, *recv;
	int req_len;

	if(match_id == 0)
		return 0;
	req_len = strlen(WVW_MATCH_DETAILS) + strlen(match_id) + 1;
	request = (char*)malloc(req_len);
	memset(request, '\0', req_len);
	strcpy_s(request, req_len, WVW_MATCH_DETAILS);
	strcat_s(request, req_len, match_id);
	recv = __cserver_request(request);
	free(request);
	return recv;
}

//requests the objective names from the server
char* _WVWObjectiveNamesRequest(int lang){
	char *request, *recv;
	int req_len;
	if(_IS_VALID_LANG(lang) != 0)
		return 0;
	req_len = strlen(WVW_OBJECTIVE_NAMES)+strlen(_LANG_DE)+1;
	request = (char*)malloc(req_len);
	memset(request, '\0', req_len);
	strcpy_s(request, req_len, WVW_OBJECTIVE_NAMES);
	switch(lang){
	case GW2API_LANG_DE:
		strcat_s(request, req_len, _LANG_DE);
		break;
	case GW2API_LANG_FR:
		strcat_s(request, req_len, _LANG_FR);
		break;
	case GW2API_LANG_EN:
		strcat_s(request, req_len, _LANG_EN);
		break;
	}
	recv = __cserver_request(request);
	free(request);
	return recv;
}


char* _itemListRequest(){
	return __cserver_request(ITEMS_API);
}


char* _itemDetailsRequest(const char *id, int lang){
	char *request, *recv;
	int size;

	if(id == 0)
		return 0;
	size = strlen(_LANG_DE)+strlen(ITEM_DETAILS)+strlen(id)+1;
	request = (char*)malloc(size);
	memset(request, '\0', size);
	strcpy_s(request, size, ITEM_DETAILS);
	strcat_s(request, size, id);
	strcat_s(request, size, "&");
	switch(lang){
	case 1:
		strcat_s(request, size, _LANG_FR);
		break;
	case 2:
		strcat_s(request, size, _LANG_EN);
		break;
	default:
		strcat_s(request, size, _LANG_DE);
		break;
	}
	recv = __cserver_request(request);
	free(request);
	return recv;
}


char* _recipeListRequest(){
	return __cserver_request(RECIPES_API);
}


char* _recipeDetailsRequest(const char *id, int lang){
	char *request, *recv;
	int size;

	if(id == 0)
		return 0;
	size = strlen(_LANG_DE)+strlen(RECIPE_DETAILS)+strlen(id)+1;
	request = (char*)malloc(size);
	memset(request, '\0', size);
	strcpy_s(request, size, RECIPE_DETAILS);
	strcat_s(request, size, id);
	strcat_s(request, size, "&");
	switch(lang){
	case 1:
		strcat_s(request, size, _LANG_FR);
		break;
	case 2:
		strcat_s(request, size, _LANG_EN);
		break;
	default:
		strcat_s(request, size, _LANG_DE);
		break;
	}
	recv = __cserver_request(request);
	free(request);
	return recv;
}


char* _guildAPIRequest(const char *id, const char *name){
	char *request, *recv;
	int size, i;

	if(id == 0 && name == 0)
		return 0;
	size = strlen(GUILD_API) + 32;
	if(id == 0)
		size += strlen(name);
	else
		size += strlen(id);
	request = (char*)malloc(size);
	memset(request, '\0', size);
	strcpy_s(request, size, GUILD_API);
	if(id == 0){
		strcat_s(request, size, "guild_name=");
		strcat_s(request, size, name);
	}
	else{
		strcat_s(request, size, "guild_id=");
		strcat_s(request, size, id);
	}
	for(i = 0; i < size; i++)
		if(request[i] == ' ')
			request[i] = '+';
	recv = __cserver_request(request);
	free(request);
	return recv;
}


char* _apiBuildRequest(){
	return __cserver_request(API_BUILD);
}


char* _colorRequest(int lang){
	char *request, *recv;
	int size;
	size = strlen(_LANG_DE)+strlen(COLORS_API)+1;
	request = (char*)malloc(size);
	memset(request, '\0', size);
	strcpy_s(request, size, COLORS_API);
	switch(lang){
	case 1:
		strcat_s(request, size, _LANG_FR);
		break;
	case 2:
		strcat_s(request, size, _LANG_EN);
		break;
	default:
		strcat_s(request, size, _LANG_DE);
		break;
	}
	recv = __cserver_request(request);
	free(request);
	return recv;
}